﻿using JetBrains.Annotations;
using PerpheralDevice.IRepository;
using PerpheralDevice.Units;
using System.Diagnostics;
using System.Serialization;

namespace AppMachine.Domain.LogicCom.AppComs;

/// <summary>
///  应用组件(开关量执行器：由输出开关控制、输入开关检测 组成的执行单元)
/// </summary>
public class ComSwitchExecutor : AppCom {


    public ComSwitchExecutorParam ComSwitchExecutorParam { get; set; }    
    public ComSwitchExecutor(IPerpDevRepository perpDevRepository, IComConfig comConfig, IComRepository comRepository)
        : base(perpDevRepository, comConfig, comRepository) {

        this.ComSwitchExecutorParam = YamlExtend.GetObject<ComSwitchExecutorParam>(this.ComConfig.ComParamSerialized) ?? new();

        this.ComSwitchExecutorParam.RwControlList.ForEach(tempItem => {
            this.mfRwControlList.Add(new Types.RwControlUnit() {
                ComSwitchRW = comRepository.GetByID<ComSwitchRW>(tempItem.SwitchRwID),
                CtlMtdName = tempItem.CtlMtdName
            });
        });

        this.ComSwitchExecutorParam.RoDetectList.ForEach(tempItem => {
            this.mfRoDetectList.Add(new Types.RoDetectUnit() {
                ComSwitchRO = comRepository.GetByID<ComSwitchRO>(tempItem.SwitchRoID),
                IsOpen = tempItem.IsOpen
            });
        });

    }

    public static class Types {
        public class RwControlUnit {
            /// <summary>
            /// 应用输出组件
            /// </summary>
            public ComSwitchRW ComSwitchRW { get; set; }
            /// <summary>
            /// 应用输出组件方法名
            /// </summary>
            public string CtlMtdName { get; set; }
        }

        public class RoDetectUnit {
            /// <summary>
            /// 等待探测的输入开关
            /// </summary>
            public ComSwitchRO ComSwitchRO { get; set; }
            /// <summary>
            /// 等待探测的输入状态
            /// </summary>
            public bool IsOpen { get; set; }
        }
    }

    public List<Types.RwControlUnit> mfRwControlList = [];
    public List<Types.RoDetectUnit> mfRoDetectList = [];
    /// <summary>
    /// 探测输入延时等待时间(毫秒)
    /// </summary>
    public int DetectDelayMiliSecs { get; set; } = 5000;

    public event Action<ComSwitchExecutor> OnPrevExecute;
    public event Action<ComSwitchExecutor> OnPostExecute;

    /// <summary>
    /// 执行
    /// </summary>
    /// <returns></returns>
    public ComSwitchExecutor Execute() {

        this.OnPrevExecute?.Invoke(this);

        foreach (var tempItem in this.mfRwControlList) {
            tempItem.ComSwitchRW.GetType().GetMethod(tempItem.CtlMtdName)?.Invoke(tempItem.ComSwitchRW, null);
        }

        ComSwitch.Wait(this.DetectDelayMiliSecs, new CancellationToken(), [.. this.mfRoDetectList.Select(it => new Tuple<bool, ComSwitch>(it.IsOpen, it.ComSwitchRO))]);

        this.OnPostExecute?.Invoke(this);

        return this;

    }

    public override AppCom Save() {
        (this.ComConfig as AppComConfig)!.ComParamSerialized = YamlExtend.GetString(this.ComSwitchExecutorParam);

        return base.Save();
    }

}
